/**
 * JAVACC DEMO 1.0
 */
package com.apache.match.server;

import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.funds.common.NumberUtil;
import com.apache.match.common.Constant;
import com.apache.match.common.GoEasyUtil;
import com.apache.cache.util.Validator;
import com.apache.client.InfoReleaseCoreCleint;
import com.apache.common.util.BigDecimalUtil;
import com.apache.database.constant.SystemTools;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.funds.common.FundsUtil;
import com.apache.info.entity.PubMetadata;
import com.apache.match.manager.DealMatchingManager;
import com.apache.match.queue.*;
import com.apache.tools.DataMap;
import com.apache.tools.DateUtils;
import com.apache.tools.DateUtils.FmtStr;
import com.apache.tools.NumberUtils;
import com.apache.tools.StrUtil;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;

import java.io.NotSerializableException;
import java.math.BigDecimal;
import java.util.*;

/**
 * description:
 *
 * @author Administrator 创建时间：2017-1-6
 */
public class DealMatchingManagerImpl_Bark implements DealMatchingManager {

    private IDao trpCateDao;

    private final String entityName = "com.apache.net.trans.TransPublic";

    private Logger log = Logger.getLogger(DealMatchingManagerImpl.class);

    private static Object obj = new Object();

    /**
     * 初始化数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public boolean loadData(ParamsVo vo) {

        //1.无条件清空缓存队列
        log.info("1.开始清空历史缓存数据...");
        SystemTools.getInstance().getCache("").removeCacheObject("MATCH_PRODUCT_FLAG");
        SystemTools.getInstance().getCache("").removeCacheObject("MATCH_INDEX");
        //清理正常完成后，自动转为暂停服务状态
        SystemTools.getInstance().getCache("").createCacheObject("InitDealMatching", "F");

        Map MATCH_INDEX = (Map) SystemTools.getInstance().getCache("")
                .getCacheObjectByKey("MATCH_INDEX");
        if (null == MATCH_INDEX) {
            MATCH_INDEX = new HashMap();//缓存不存在
            SystemTools.getInstance().getCache("").createCacheObject("MATCH_INDEX", MATCH_INDEX);
        }
        log.info("2.查询行情中正在交易的商品列表...");
        //2.从行情中获取正在交易的商品列表。
        String proQuotationSql = "select * from t_quotation t where t.status ='T'";
        MethodParam paramQuotai = new MethodParam("ByObjInfo", "", "", entityName);
        paramQuotai.setParams("dyncSql", proQuotationSql);
        List quoProList = trpCateDao.select(paramQuotai);
        log.info("3.行情中正在交易的商品数：" + quoProList.size());
        if (quoProList != null && quoProList.size() > 0) {
            int q = 0;
            for (Object qpro : quoProList) {
                q++;
                DataMap proMap = (DataMap) qpro;
                String proId = String.valueOf(proMap.get("proId"));
                String proNo = String.valueOf(proMap.get("proNo"));
                try {
                    String proName = String.valueOf(proMap.get("proName"));
                    log.info("-");
                    log.info("开始加载第【" + q + "】个[" + proNo + "]-[" + proName
                            + "]商品的未成交委托挂单信息>>>>>>>>>>>>>>>>>>>>>>>");

                    //2.1遍历查询每个商品下面的所有挂单信息，加载到各自缓存队列内
                    String orderSql = "select * from trs_order s where s.pro_id='" + proId
                            + "' and s.order_date = '" + DateUtils.Now.fmt_yyyyMMdd()
                            + "' and s.is_kill='F' and (s.is_deal='F' or s.is_deal='T0') and s.del_status='F'   order by order_flag asc,order_price+0 desc,order_time+0 asc";
                    MethodParam paramOrder = new MethodParam("ByObjInfo", "", "", entityName);
                    paramOrder.setParams("dyncSql", orderSql);
                    List objs = trpCateDao.select(paramOrder);
                    IndexQueue indexQueue = new IndexQueue();
                    DataMap orderBuyFirst = null;
                    if (Validator.isEmpty(objs)) {
                        log.info("商品下委托单条数：0");
                        continue;
                    }
                    int count = objs.size();
                    log.info("商品下委托单条数：" + count);
                    if (count > 0) {
                        DataMap orderBuyFirstObj = (DataMap) objs.get(0);
                        String firstFlag = String.valueOf(orderBuyFirstObj.get("orderFlag"));
                        if (orderBuyFirstObj != null && "buy".equals(firstFlag)) {
                            orderBuyFirst = orderBuyFirstObj;
                        }

                        for (int i = 0; i < count; i++) {
                            DataMap<String> order = (DataMap) objs.get(i);
                            String orderKey = String.valueOf(order.get("orderNo")) + "###" + String
                                    .valueOf(order.get("proId"));
                            BigDecimal b = BigDecimalUtil.getInstance()
                                    .multiply(StrUtil.doNull(order.get("dealPrice"), "0"), "100");
                            order.put("deal_price", String.valueOf((long) (Double
                                    .valueOf(StrUtil.doNull(order.get("dealPrice"), "0")) * 100)));

                            indexQueue = addQueue(MATCH_INDEX, (Map) order, new IndexQueue());
                        }
                    }
                    log.info("[" + proNo + "]-[" + proName + "]商品数据加载完成！");

                    //将组装好的买卖队列进行匹配
                    if (orderBuyFirst != null) {
                        log.info("[" + proNo + "]-[" + proName + "]商品，存在买入单，需执行撮合匹配！！！！！！");
                        matching(MATCH_INDEX, indexQueue, orderBuyFirst);
                    } else {
                        log.info("[" + proNo + "]-[" + proName + "]商品，无买入单，无需执行撮合匹配！");
                    }
                } catch (Exception ex) {
                    if (ex instanceof NotSerializableException) {
                        //ex.printStackTrace();
                        MethodParam param = new MethodParam("ByQuotationUpdate", "", "",
                                entityName);
                        param.setParams("proNo", proNo);
                        trpCateDao.select(param);
                    }
                }
            }
            //SystemTools.getInstance().getCache("").createCacheObject("MATCH_INDEX", MATCH_INDEX);
        } else {
            log.info("系统行情中：无正在交易的商品...");
        }
        log.info("初始化所有交易商品下，未成交委托单数据完成！");
        return false;

    }

    @SuppressWarnings("rawtypes")
    public boolean saveInvoke(ParamsVo vo) {
        String key = StrUtil.doNull(vo.getMethodKey(), "ByDymicSql");//ByQuotationUpdate
        MethodParam param = new MethodParam(key, "", "", entityName);
        boolean mark = false;
        if (Validator.isNotNull(String.valueOf(vo.getParams("sqlStr")))) {
            param.setParams("execSql", String.valueOf(vo.getParams("sqlStr")));
            mark = trpCateDao.edit(param);
        }
        String ifUpdate = String.valueOf(vo.getParams("ifUpdate"));
        if (Validator.isNull(ifUpdate)) {
            param.setKey("ByQuotationUpdate");
            param.setParams("proNo", String.valueOf(vo.getParams("proNo")));
            param.setParams("execSql", "");
            trpCateDao.select(param);
        }
        return true;
    }

    /**
     * 挂单调用
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public boolean saveInfo(ParamsVo vo) {

        log.info("接收的委托信息：" + vo.getParams());

        Map<String, String> map = (Map) vo.getParams("resultEntity");
        String orderId = String.valueOf(map.get("trsOrder_orderId"));
        if (!Validator.isNull(orderId)) {
            MethodParam param = new MethodParam("ByObjInfo", "", "", entityName);
            param.setParams("dyncSql", "select * from trs_order where order_id='" + orderId + "'");
            DataMap<String> orderInfoMap = (DataMap) trpCateDao.selectSingle(param);
            try {
                Map<String, String> MATCH_PRODUCT_FLAG = (Map<String, String>) SystemTools
                        .getInstance().getCache("").getCacheObjectByKey("MATCH_PRODUCT_FLAG");
                if (null == MATCH_PRODUCT_FLAG) {
                    MATCH_PRODUCT_FLAG = new HashMap<String, String>();
                    SystemTools.getInstance().getCache("")
                            .createCacheObject("MATCH_PRODUCT_FLAG", MATCH_PRODUCT_FLAG);
                }
                String orderKey = "matchProduct_" + orderId;
                String strMatchProductFlag = MATCH_PRODUCT_FLAG.get(orderKey);
                if (null == strMatchProductFlag || "wait".equals(strMatchProductFlag)) {
                    MATCH_PRODUCT_FLAG.put(orderKey, "run");
                }

                boolean mark = true;
                String orderFlag = orderInfoMap.get("orderFlag"); //买：buy，卖：sell

                String moneyStr = String.valueOf(vo.getParams("money"));//获取传入计算的金额值
                double money = NumberUtils.getDouble(moneyStr, 0, false);//资金转换：为空默认0
                String userSettleNo = String.valueOf(vo.getParams("userSettleNo"));//资金账号
                String orderNo = String.valueOf(vo.getParams("trsOrder.orderNo"));//委托单号

                String createUserEname = orderInfoMap.get("createUser");
                String settleNo = getUserSettleNo(createUserEname);

                /**1）、处理资金 ***************************/
                if ("sell".equals(orderFlag)) {
                    //挂卖单：冻结卖方手续费
                    if (money > 0) {
                        //					log.info("开始冻结卖方手续费：" + money);
                        //					mark = toFundsForzenOrUn(userSettleNo, Constant.Funds.PBOD, money, orderNo, "委托卖出手续费冻结");
                    }
                } else {
                    //挂买单：冻结买方资金（交易金额+手续费）
                    if (money > 0) {
                        log.info("开始冻结买方资金（交易金额+手续费）：" + money);
                        mark = toFundsForzenOrUn(userSettleNo, Constant.Funds.PBOD, money, orderNo,
                                "委托买入交易资金冻结");
                    }
                }
                if (!mark) {
                    return false;
                }

                /**2）、处理持仓 ***************************/
                StringBuilder updateGoods = new StringBuilder();
                if ("sell".equals(orderFlag)) {
                    //挂卖单： 冻结卖方持仓
                    String dataType = Constant.getDatabaseType("nyt");
                    if ("oracle".equalsIgnoreCase(dataType)) {
                        updateGoods
                                .append("update trs_goods t set t.use_num = to_number(t.use_num)-to_number('"
                                        + orderInfoMap.get("orderNum")
                                        + "'),t.forzen_num=to_number(t.forzen_num)+to_number('"
                                        + orderInfoMap.get("orderNum") + "'),t.modify_time='"
                                        + DateUtils.Now.fmt_yyyyMMdd_HHmmss() + "' "
                                        + " where t.pro_id='" + orderInfoMap.get("proId")
                                        + "' and t.user_id='" + orderInfoMap.get("userId") + "'");
                    } else {
                        updateGoods
                                .append("update trs_goods t set t.use_num = cast(t.use_num as unsigned int)-cast("
                                        + orderInfoMap.get("orderNum") + " as unsigned int)"
                                        + ",t.forzen_num=cast(t.forzen_num as unsigned int)+cast("
                                        + orderInfoMap.get("orderNum")
                                        + " as unsigned int),t.modify_time='" + DateUtils.Now
                                        .fmt_yyyyMMdd_HHmmss() + "' " + " where t.pro_id='"
                                        + orderInfoMap.get("proId") + "' and t.user_id='"
                                        + orderInfoMap.get("userId") + "'");
                    }

                    MethodParam updateGoodsParam = new MethodParam("ByDymicSqlOnly", "", "",
                            entityName);
                    updateGoodsParam.setParams("execSql", updateGoods.toString());
                    mark = trpCateDao.edit(updateGoodsParam);
                }
                if (!mark) {
                    return false;
                }
                //挂单时封装买卖队列
                Map MATCH_INDEX = (Map) SystemTools.getInstance().getCache("")
                        .getCacheObjectByKey("MATCH_INDEX");
                if (null == MATCH_INDEX) {
                    MATCH_INDEX = new HashMap();//缓存不存在
                    SystemTools.getInstance().getCache("")
                            .createCacheObject("MATCH_INDEX", MATCH_INDEX);
                }
                if (Validator.isNull(orderInfoMap.get("orderId"))) {
                    orderInfoMap.put("order_id", orderId);
                }
                synchronized (obj) {
                    IndexQueue indexQueue = addQueue(MATCH_INDEX, (Map) orderInfoMap,
                            new IndexQueue());

                    //将组装好的买卖队列进行匹配
                    matching(MATCH_INDEX, indexQueue, orderInfoMap);

                    ParamsVo pvo = new ParamsVo();
                    pvo.setParams("proNo", orderInfoMap.get("proNo"));
                    pvo.setParams("sqlStr", "");
                    saveInvoke(pvo);
                }
                //SystemTools.getInstance().getCache("").createCacheObject("MATCH_INDEX", MATCH_INDEX);
            } catch (Exception ex) {
                if (ex instanceof NotSerializableException) {
                    param = new MethodParam("ByQuotationUpdate", "", "", entityName);
                    param.setParams("proNo", orderInfoMap.get("proNo"));
                    trpCateDao.select(param);
                    //ex.printStackTrace();
                }
            }
        }
        return true;
    }

    /**
     * TODO 撤单
     *
     * @see DealMatchingManager#resultOrder(ParamsVo)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public boolean resultOrder(ParamsVo vo) {
        boolean mark = false;
        log.info("开始撤单....");
        Map MATCH_INDEX = (Map) SystemTools.getInstance().getCache("")
                .getCacheObjectByKey("MATCH_INDEX");
        String orderId = String.valueOf(vo.getParams("trsOrder.orderId"));
        vo.setMethodKey("ByDymicSqlOnly");
        MethodParam param = new MethodParam("ByObjInfo", "", "", entityName);
        param.setParams("dyncSql", "select * from trs_order where order_id='" + orderId + "'");
        DataMap<String> orderInfoMap = (DataMap) trpCateDao.selectSingle(param);//用ID获取订单信息
        log.info("撤单对象：" + orderInfoMap);

        if ("T".equals(orderInfoMap.get("isDeal")) || "T"
                .equals(orderInfoMap.get("isKill"))) {//成交的或已撤销的不能撤销
            vo.setParams("result-mssage", "撤单失败：委托单状态不合法！");
            return false;
        }
        vo.setParams("trsOrder.proNo", orderInfoMap.get("proNo"));//成功后为调行情使用
        if (null == MATCH_INDEX) {//缓存不存在时直接修改数据库
            vo.setMethodKey("ByDymicSql");
            vo.setParams("sqlStr", resultOrderSql(orderInfoMap, orderId));//生成撤单SQL，解冻资金
            vo.setParams("proNo", orderInfoMap.get("ProNo"));
            vo.setParams("ifUpdate", "ddd");
            saveInvoke(vo);
            log.info("缓存不存在时直接修改数据库");
            return true;
        }

        String proId = String.valueOf(vo.getParams("trsOrder.proId"));
        String orderKey = "indexList###" + proId + "###";//订单索引
        IndexQueue iq = (IndexQueue) MATCH_INDEX.get(orderKey);
        String orderType = orderInfoMap.get("orderFlag");
        List list = iq.getQueue(orderType);
        if (Validator.isEmpty(list)) {//缓存对列不存在时直接修改数据库
            vo.setMethodKey("ByDymicSql");
            vo.setParams("sqlStr", resultOrderSql(orderInfoMap, orderId));
            vo.setParams("proNo", orderInfoMap.get("ProNo"));
            vo.setParams("ifUpdate", "ddd");
            saveInvoke(vo);
            log.info("对列不存在时直接修改数据库");
            return true;
        }
        int count = list.size();
        List tempList = new ArrayList();
        for (int i = 0; i < count; i++) {//循环队列
            SupperQueue sq = (SupperQueue) list.get(i);
            DataMap data = (DataMap) sq.getObj();
            if (!orderId.equals(data.get("orderId")))//验证是否是待撤销订单
                continue;
            if ("T".equals(data.get("isState"))) {//撮合中的不能撤销
                vo.setParams("result-mssage", "撤单失败：委托单正在撮合中！");
                return false;
            }
            if ("T".equals(data.get("isDeal")) || "T".equals(data.get("isKill"))) {//成交的或已撤销的不能撤销
                vo.setParams("result-mssage", "撤单失败：委托单状态不合法！");
                return false;
            }

            vo.setMethodKey("ByDymicSql");
            vo.setParams("sqlStr", resultOrderSql(data, String.valueOf(data.get("orderId"))));
            vo.setParams("proNo", orderInfoMap.get("ProNo"));
            vo.setParams("ifUpdate", "ddd");
            saveInvoke(vo);
            log.info("数据库此委托撤销完成。");
            tempList.add(sq);
        }
        list.removeAll(tempList);
        log.info("缓存队列移除完成。");
        return true;
    }

    /**
     * 生成撤单sql
     */
    @SuppressWarnings("rawtypes")
    private String resultOrderSql(DataMap data, String orderId) {
        String orderType = String.valueOf(data.get("orderFlag"));
        StringBuffer sb = new StringBuffer();
        sb.append("update trs_order set is_kill='T', modify_time='" + DateUtils.Now
                .fmt_yyyyMMdd_HHmmss() + "' where order_id='" + orderId + "';");//修改订单状态为已撤销

        if ("buy".equalsIgnoreCase(orderType)) {//买方结冻资金
            String userSettleNo = getUserSettleNo(String.valueOf(data.get("userEname")));//fee_ratio
            //总金额
            double totalMoney = NumberUtils
                    .multiply(Double.valueOf(String.valueOf(data.get("orderPrice"))),
                            Double.valueOf(String.valueOf(data.get("orderNum"))) - NumberUtils
                                    .getDouble(String.valueOf(data.get("dealNum")), 0, true), 2);
            //应该解冻手续费
            double sellFeeRate = NumberUtils
                    .divide(Double.valueOf(String.valueOf(data.get("feeRatio"))),
                            100);//除以100，因为页面设置的单位是%
            sellFeeRate = NumberUtils.multiply(totalMoney, sellFeeRate, 2);
            totalMoney = NumberUtils.add(totalMoney, sellFeeRate);
            log.info("撤销[buy]委托单[" + String.valueOf(data.get("orderNo")) + "]解冻金额：" + totalMoney);
            boolean fa = toFundsForzenOrUn(userSettleNo, Constant.Funds.CBOD, totalMoney,
                    String.valueOf(data.get("orderNo")), "撤单解冻资金");
            if (!fa) {
                log.info("撤销[buy]委托单[" + String.valueOf(data.get("orderNo")) + "]撤单解冻操作失败：" + fa);
            } else {
                log.info("撤销[buy]委托单[" + String.valueOf(data.get("orderNo")) + "]撤单解冻操作成功：" + fa);
            }
        } else {//卖方解冻持仓
            String dealNumStr = Validator.getDefaultStr(String.valueOf(data.get("dealNum")), "0");
            long orderNum = Long.valueOf(String.valueOf(data.get("orderNum")));
            long dealNum = Long.valueOf(dealNumStr);
            log.info("撤销[sell]委托单[" + String.valueOf(data.get("orderNo")) + "]解冻持仓：" + (orderNum
                    - dealNum));
            String dataType = Constant.getDatabaseType("nyt");
            if ("oracle".equalsIgnoreCase(dataType)) {
                sb.append("update trs_goods set forzen_num=to_number(forzen_num)-to_number('" + (
                        orderNum - dealNum) + "') ,use_num=to_number(use_num)+to_number('" + (
                        orderNum - dealNum) + "'),modify_time='" + DateUtils.Now
                        .fmt_yyyyMMdd_HHmmss() + "' where pro_id='" + data.get("proId")
                        + "' and user_id='" + data.get("userId") + "';");
            } else {
                sb.append(
                        "update trs_goods set forzen_num=cast(forzen_num as unsigned int)-cast(" + (
                                orderNum - dealNum)
                                + " as unsigned int) ,use_num=cast(use_num as unsigned int)+cast("
                                + (orderNum - dealNum) + " as unsigned int),modify_time='"
                                + DateUtils.Now.fmt_yyyyMMdd_HHmmss() + "' where pro_id='" + data
                                .get("proId") + "' and user_id='" + data.get("userId") + "';");
            }
        }
        return sb.toString();
    }

    /**
     * description:
     *
     * @param order
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void matching(Map MATCH_INDEX, IndexQueue iq, DataMap<String> order)
            throws NotSerializableException {
        //		addQueue(MATCH_INDEX, order, indexQueue);
        //拿出买卖两个队列，进行匹配
        List sellList = iq.getQueue("sell");
        List buyList = iq.getQueue("buy");
        //匹配完成，生成相关sql。在清空原有队列的同时将剩余订单放入到队列中。
        String sql = matchOrder(order, buyList, sellList);
        //		IndexQueue indexQueue = addQueue(MATCH_INDEX, (Map) orderInfoMap, new IndexQueue());
        //		String sql = matchOrder(order, orderType, list, orderTime, orderNum, priceUnit, templist);
        if (StrUtil.isNotNull(sql)) {///需要操作一下数据库更新插入信息
            log.info("===============================sql:" + sql);
            ParamsVo vo = new ParamsVo();
            vo.setParams("proNo", order.get("proNo"));
            vo.setParams("sqlStr", sql);
            saveInvoke(vo);
            iq.removeAll();
            iq.setListAll(buyList, sellList);

            String orderKey = "indexList###" + String.valueOf(order.get("proId")) + "###";//订单索引
            MATCH_INDEX.put(orderKey, iq);//将队列放入缓存
            log.info("撮合完成后：");
            if (iq != null) {
                iq.print();
            }

            /**撮合成交后：[行情推送]给前端推送发生行情变化的商品proId**/
            String proId = order.get("proId");
            String proNo = order.get("proNo");
            GoEasyUtil.pushGoEasyMsg("pro_quotation", proId);

            SystemTools.getInstance().getCache("").createCacheObject("MATCH_INDEX", MATCH_INDEX);

        }
    }

    /**
     * description:
     *
     * @param MATCH_INDEX
     * @param order 订单
     * @param indexQueue 顺序队列
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private IndexQueue addQueue(Map MATCH_INDEX, Map<String, Object> order, IndexQueue indexQueue) {
        if (!Validator.isEmpty(order)) {
            String orderKey = "indexList###" + String.valueOf(order.get("proId")) + "###";//订单索引
            String orderType = String.valueOf(order.get("orderFlag"));//买卖单方向 ： buy-挂买 ，sell-挂卖
            String proNo = String.valueOf(order.get("proNo"));//买卖单方向 ： buy-挂买 ，sell-挂卖

            String tradeTime = String.valueOf(order.get("orderTime"));//挂单时间  字符串类型 yyyy-mm-dd
            if (Validator.isNull(tradeTime)) {
                tradeTime = String.valueOf(DateUtils
                        .strToLong(String.valueOf(order.get("createTime")),
                                FmtStr.yyyyMMdd_HHmmss));
                order.put("orderTime", tradeTime);
            }
            long orderTime = Long.valueOf(tradeTime);//挂单时间（long类型）
            long priceUnit = (long) (Double.valueOf(String.valueOf(order.get("orderPrice")))
                    * 100);//挂单价格
            long orderNum = Long.valueOf(String.valueOf(order.get("orderNum")));//挂单数量
            SupperQueue queue = null;
            //			if (!Validator.isEmpty(indexQueue)) {
            //				indexQueue.print();
            //			}

            Object matchObj = MATCH_INDEX.get(orderKey);
            if (matchObj != null) {
                indexQueue = (IndexQueue) matchObj;
            }

            if ("buy".equalsIgnoreCase(orderType)) {
                queue = new QueueDesc(priceUnit, orderTime, orderNum, order);//买方队列
            } else {
                queue = new QueueAsc(priceUnit, orderTime, orderNum, order);//卖方队列
            }
            indexQueue.insertOrUpdate(queue);//组装队列
            MATCH_INDEX.put(orderKey, indexQueue);//将队列放入缓存

            log.info("新增[" + proNo + "]的[" + orderType + "]队列后：");
            if (indexQueue != null) {
                indexQueue.print();
            }
        }
        return indexQueue;
    }

    /**
     * order 挂单信息
     * orderType 挂单类型 buy：买 sell：卖
     * list 顺序队列
     * orderTime 挂单时间
     * orderNum 挂单数量
     * priceUnit 价格（乘以100后的值）
     * templist 临时队列
     * description:  遍历队列中从head到aNode节点的所有节点
     */
    private String matchOrder(DataMap<String> order, List<SupperQueue> buyList,
            List<SupperQueue> sellList) {

        StringBuffer sb = new StringBuffer();

        if (buyList.size() == 0 || sellList.size() == 0) {
            log.info("无可用匹配数据");
        } else {
            sb.append(matchBuySell(order, buyList, sellList));

        }

        return sb.toString();
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private String matchBuySell(DataMap<String> order, List<SupperQueue> buyList,
            List<SupperQueue> sellList) {
        StringBuffer execSql = new StringBuffer();
        int buyIndex = 0, sellIndex = 0;
        List<SupperQueue> buyTemp = new ArrayList<SupperQueue>();
        List<SupperQueue> sellTemp = new ArrayList<SupperQueue>();
        String proId = String.valueOf(order.get("proId"));
        String proNo = String.valueOf(order.get("proNo"));
        String proName = String.valueOf(order.get("proName"));
        String now = DateUtils.Now.fmt_yyyyMMdd_HHmmss();
        BigDecimal beiBig = new BigDecimal("100");
        boolean isRun = true;
        String dataType = Constant.getDatabaseType("nyt");
        for (int i = buyIndex; i < buyList.size(); i++) {
            if (!isRun) {
                break;//控制无可匹配后，跳出循环，终止大循环匹配
            }
            SupperQueue buyQueue = buyList.get(i);
            DataMap buyObjMap = (DataMap) buyQueue.getObj();
            String buyUserId = String.valueOf(buyObjMap.get("userId"));
            buyObjMap.put("is_state", "T");
            for (int j = sellIndex; j < sellList.size(); j++) {
                SupperQueue sellQueue = sellList.get(j);
                DataMap sellObjMap = (DataMap) sellQueue.getObj();
                sellObjMap.put("is_state", "T");
                String sellUserId = String.valueOf(sellObjMap.get("userId"));
                BigDecimal buyOrderNum = BigDecimalUtil.getInstance()
                        .subtract(String.valueOf(buyObjMap.get("orderNum")), Validator
                                .getDefaultStr(String.valueOf(buyObjMap.get("dealNum")),
                                        "0"));//买单剩余未成交数量
                BigDecimal sellOrderNum = BigDecimalUtil.getInstance()
                        .subtract(String.valueOf(sellObjMap.get("orderNum")), Validator
                                .getDefaultStr(String.valueOf(sellObjMap.get("dealNum")),
                                        "0")); //卖单挂单数量
                if (buyOrderNum.longValue() == 0) {
                    buyTemp.add(buyQueue);
                    break;
                }
                if (sellOrderNum.longValue() == 0) {
                    sellTemp.add(sellQueue);
                    continue;
                }

                log.info("开始匹配第i=" + i + ",j=" + j + "-------------------------------");
                log.info("sell" + j + "：price=" + String.valueOf(sellObjMap.get("orderPrice"))
                        + ",orderNum=" + String.valueOf(sellObjMap.get("orderNum")) + ",dealNum="
                        + String.valueOf(sellObjMap.get("dealNum")) + ",orderNo=" + String
                        .valueOf(sellObjMap.get("orderNo")) + "。" + sellObjMap);
                log.info("buy" + i + "：price=" + String.valueOf(buyObjMap.get("orderPrice"))
                        + ",orderNum=" + String.valueOf(buyObjMap.get("orderNum")) + ",dealNum="
                        + String.valueOf(buyObjMap.get("dealNum")) + ",orderNo=" + String
                        .valueOf(buyObjMap.get("orderNo")) + "。" + buyObjMap);
                //判断是否满足成交条件（买价>=卖价）
                BigDecimal buyPrice = new BigDecimal(String.valueOf(buyQueue.getPriceUnit()));
                BigDecimal sellPrice = new BigDecimal(String.valueOf(sellQueue.getPriceUnit()));
                BigDecimal dealPrice = buyPrice;//本次成交价格

                if (BigDecimalUtil.getInstance().ge(buyPrice, sellPrice)) {//buyPrice>=sellPrice
                    //1.确定成交价
                    if (buyPrice.compareTo(sellPrice) == 0) {
                        dealPrice = buyPrice;
                    } else {
                        //获取成交价
                        //							dealPrice = NumberUtil.getABS(buyPrice, num2, num3);
                        dealPrice = BigDecimalUtil.getInstance().getBigDecimal(
                                getDealPriceNew(proId, buyPrice.longValue(),
                                        sellPrice.longValue()));
                    }

                    //2.确定成交量
                    BigDecimal dealNum = new BigDecimal("0");//本次成交数量

                    BigDecimal buyTotalDealNum = new BigDecimal("0");//买单成交总数量
                    BigDecimal sellTotalDealNum = new BigDecimal("0");//卖单成交总数量

                    BigDecimal buyTotalDealPrice = new BigDecimal("0");//买单成交总价格
                    BigDecimal sellTotalDealPrice = new BigDecimal("0");//卖单成交总数量
                    BigDecimal buyFee = new BigDecimal("0");//买单成交手续费
                    BigDecimal sellFee = new BigDecimal("0");//卖单成交手续费
                    BigDecimal buyFeeRate = BigDecimalUtil.getInstance()
                            .divide(String.valueOf(buyObjMap.get("feeRatio")), "100");//买单成交手续费率

                    BigDecimal sellFeeRate = BigDecimalUtil.getInstance()
                            .divide(String.valueOf(sellObjMap.get("feeRatio")), "100");//卖单成交手续费率
                    BigDecimal buyLastDealNum = new BigDecimal(
                            StrUtil.doNull(String.valueOf(buyObjMap.get("dealNum")),
                                    "0"));//买方上次成交数量（累计值）
                    BigDecimal buyLastDealPrice = new BigDecimal(
                            StrUtil.doNull(String.valueOf(buyObjMap.get("dealPrice")),
                                    "0"));//买方上次成交价格（累计值）
                    BigDecimal sellLastDealNum = new BigDecimal(
                            StrUtil.doNull(String.valueOf(sellObjMap.get("dealNum")),
                                    "0"));//卖方上次成交数量（累计值）
                    BigDecimal sellLastDealPrice = new BigDecimal(
                            StrUtil.doNull(String.valueOf(sellObjMap.get("dealPrice")),
                                    "0"));//卖方上次成交价格（累计值）

                    if (buyOrderNum.longValue() > sellOrderNum
                            .longValue()) {//buyOrderNum > sellOrderNum买单剩余未成交数量>卖单剩余未成交数量，则认为卖单全部成交，买单部分成交。成交数量以小者（卖单）为准
                        dealNum = sellOrderNum;
                        if (dealNum.longValue() == 0) {
                            System.out.println("-----");
                        }
                        log.info("本次成交量：" + dealNum + "，成交价：" + dealPrice);

                        //计算买单成交均价

                        buyTotalDealNum = BigDecimalUtil.getInstance()
                                .add(buyLastDealNum.toString(), dealNum.toString());
                        buyTotalDealPrice = BigDecimalUtil.getInstance()
                                .add(BigDecimalUtil.getInstance()
                                                .divide(dealNum.multiply(dealPrice), beiBig, 2),
                                        BigDecimalUtil.getInstance()
                                                .divide(buyLastDealNum.multiply(buyLastDealPrice),
                                                        beiBig, 2), 2);
                        buyFee = BigDecimalUtil.getInstance()
                                .multiply(buyTotalDealPrice, buyFeeRate, 2);
                        BigDecimal buyTotalAmount = BigDecimalUtil.getInstance()
                                .add(buyFee, buyTotalDealPrice, 2);//总金额（含手续费）
                        BigDecimal buyDealAvgPrice = BigDecimalUtil.getInstance()
                                .divide(buyTotalDealPrice, buyTotalDealNum, 2);
                        //计算卖单成交均价
                        sellTotalDealNum = BigDecimalUtil.getInstance()
                                .add(sellLastDealNum.toString(), dealNum.toString());
                        sellTotalDealPrice = BigDecimalUtil.getInstance()
                                .add(BigDecimalUtil.getInstance()
                                                .divide(dealNum.multiply(dealPrice), beiBig, 2),
                                        BigDecimalUtil.getInstance()
                                                .divide(sellLastDealNum.multiply(sellLastDealPrice),
                                                        beiBig, 2), 2);
                        sellFee = BigDecimalUtil.getInstance()
                                .multiply(sellTotalDealPrice, sellFeeRate, 2);
                        BigDecimal sellTotalAmount = BigDecimalUtil.getInstance()
                                .add(sellFee, sellTotalDealPrice, 2);//总金额（含手续费）
                        BigDecimal sellDealAvgPrice = BigDecimalUtil.getInstance()
                                .divide(sellTotalDealPrice, sellTotalDealNum, 2);

                        //卖单成交标记更新：update trs_order set is_deal='T',deal_num=order_num ,deal_price = '"+dealPrice+"' where order_id = orderId;
                        //买单成交标记更新：update trs_order set is_deal='T0',deal_num='"+dealNum+"' ,deal_price = '"+dealPrice+"' where order_id = orderId;
                        execSql.append(
                                "update trs_order set is_deal='T',deal_num=order_num ,deal_price = '");
                        execSql.append(
                                sellDealAvgPrice + "',modify_time='" + now + "' where order_id = '"
                                        + sellObjMap.get("orderId") + "';");
                        execSql.append(
                                "update trs_order set is_deal='T0',deal_num='" + buyTotalDealNum);
                        execSql.append(
                                "' ,deal_price = '" + buyDealAvgPrice + "',modify_time='" + now
                                        + "' where order_id = '" + buyObjMap.get("orderId") + "';");
                        //买方-------------------------------------------------------------------------------------------------
                        buyObjMap.put("deal_num", buyTotalDealNum);
                        buyObjMap.put("deal_price", BigDecimalUtil.getInstance()
                                .multiply(buyDealAvgPrice.toString(), "100"));
                        buyObjMap.put("is_deal", "T0");//部分成交标记
                        //更新买方持仓：如果之前没有，则插入新的数据，如果之前已经存在仓位，则更新这条数据。
                        //联合主键：proId+userId
                        execSql.append("merge into trs_goods goods using (select '" + proId
                                + "' as pro_id,'");
                        execSql.append(buyUserId + "' as user_id from dual) m ");
                        execSql.append(
                                "on (goods.pro_id=m.pro_id and goods.user_id=m.user_id) when matched then  ");
                        if ("oracle".equalsIgnoreCase(dataType)) {
                            execSql.append(
                                    "update set goods.total_num=to_number(goods.total_num)+to_number('");//加持仓总量
                            execSql.append(dealNum
                                    + "'), goods.forzen_num=to_number(goods.forzen_num)+to_number('");//加冻结持仓量
                            execSql.append(dealNum + "'),goods.modify_time='" + now
                                    + "',goods.buy_price=round(to_number(goods.buy_price)+to_number('"
                                    + buyTotalAmount//成本价，包含手续费
                                    + "'),2) ");
                            execSql.append(
                                    ",goods.cost_price=round((to_number(goods.buy_price)+to_number('"
                                            + buyTotalAmount
                                            + "'))/(to_number(goods.total_num)+to_number('"
                                            + dealNum + "')),2) ");
                        } else {
                            execSql.append(
                                    "update set goods.total_num=cast(goods.total_num as unsigned int)+cast(");//加持仓总量
                            execSql.append(dealNum
                                    + " as unsigned int), goods.forzen_num=cast(goods.forzen_num as unsigned int)+cast(");//加冻结持仓量
                            execSql.append(dealNum + " as unsigned int),goods.modify_time='" + now
                                    + "',goods.buy_price=round(cast(goods.buy_price as unsigned DECIMAL)+cast("
                                    + buyTotalAmount//成本价，包含手续费
                                    + " as unsigned DECIMAL),2) ");
                            execSql.append(
                                    ",goods.cost_price=round((cast(goods.buy_price as unsigned DECIMAL)+cast("
                                            + buyTotalAmount
                                            + " as unsigned DECIMAL))/(cast(goods.total_num as unsigned int)+cast("
                                            + dealNum + " as unsigned int)),2) ");
                        }
                        execSql.append(
                                "when not matched then  insert (goods.goods_id,goods.user_id,goods.pro_id,pro_no,pro_name,total_num,forzen_num,create_time,del_status,user_ename,user_cname,use_num,buy_price,cost_price) ");
                        execSql.append(
                                "values ('" + Validator.generate() + "','" + buyUserId + "','"
                                        + proId + "','");
                        execSql.append(
                                proNo + "','" + proName + "','" + dealNum + "','" + dealNum + "','"
                                        + now + "','F','" + String
                                        .valueOf(buyObjMap.get("userEname")) + "','" + String
                                        .valueOf(buyObjMap.get("userCname")) + "','0','"
                                        + buyTotalAmount + "','" + BigDecimalUtil.getInstance()
                                        .divide(buyTotalAmount.toString(),
                                                buyTotalDealNum.toString(), 2) + "');");
                        //卖方-------------------------------------------------------------------------------------------------
                        sellObjMap.put("deal_num", sellTotalDealNum);
                        sellObjMap.put("deal_price", BigDecimalUtil.getInstance()
                                .multiply(sellDealAvgPrice.toString(), "100"));
                        sellObjMap.put("is_deal", "T");//全部成交标记
                        //更新卖方持仓
                        if ("oracle".equalsIgnoreCase(dataType)) {
                            execSql.append(
                                    "update trs_goods goods set goods.total_num=to_number(goods.total_num)-to_number('");
                            execSql.append(dealNum
                                    + "'),goods.forzen_num=to_number(goods.forzen_num)-to_number('");
                            execSql.append(dealNum + "'),goods.modify_time='" + now
                                    + "',goods.buy_price=round(to_number(goods.buy_price)-to_number('"
                                    + sellTotalDealPrice + "')+to_number('" + sellFee
                                    + "'),2),goods.cost_price=round((to_number(goods.buy_price)-to_number('"
                                    + sellTotalDealPrice + "')+to_number('" + sellFee
                                    + "'))/(to_number(goods.total_num)-to_number('" + dealNum
                                    + "')),2) where goods.pro_id='" + proId
                                    + "' and goods.user_id='");
                        } else {
                            execSql.append(
                                    "update trs_goods goods set goods.total_num=cast(goods.total_num as unsigned int)-cast(");
                            execSql.append(dealNum
                                    + " as unsigned int),goods.forzen_num=cast(goods.forzen_num as unsigned int)-cast(");
                            execSql.append(dealNum + " as unsigned int),goods.modify_time='" + now
                                    + "',goods.buy_price=round(cast(goods.buy_price as unsigned DECIMAL)-cast("
                                    + sellTotalDealPrice + " as unsigned DECIMAL)+cast(" + sellFee
                                    + " as unsigned DECIMAL),2),goods.cost_price=round((cast(goods.buy_price as unsigned DECIMAL)-cast("
                                    + sellTotalDealPrice + " as unsigned DECIMAL)+cast(" + sellFee
                                    + " as unsigned DECIMAL))/(cast(goods.total_num as unsigned int)-cast("
                                    + dealNum + " as unsigned int)),2) where goods.pro_id='" + proId
                                    + "' and goods.user_id='");
                        }
                        execSql.append(sellUserId + "';");
                        //						String proId, String dealPrice, String buyEname, String buyCname, String buyUserId,
                        //						String sellEname, String sellerCname, String sellUserId, String proName, String dealNum
                        execSql.append(
                                insertDeal(proId, String.valueOf(dealPrice), buyObjMap, sellObjMap,
                                        proName, String.valueOf(dealNum)));
                        //已成交的委托挂单插入到order_done表中。当前为卖单

                        execSql.append(
                                "insert into trs_order_done (info_id,create_time,deal_date,deal_fee,deal_num,deal_price,deal_time,del_status,order_flag,order_id,order_no,pro_id,pro_name,pro_no,total_money,user_cname,user_ename,user_id)");
                        execSql.append("values('" + Validator.generate() + "','" + now + "','"
                                + DateUtils.Now.fmt_yyyyMMdd() + "','" + sellFee + "','"
                                + sellTotalDealNum + "','" + sellDealAvgPrice + "','" + now
                                + "','F','sell','" + sellObjMap.get("orderId") + "','" + sellObjMap
                                .get("orderNo") + "','" + proId + "','" + proName + "','" + proNo
                                + "','" + sellTotalAmount + "','" + sellObjMap.get("userCname")
                                + "','" + sellObjMap.get("userEname") + "','" + sellObjMap
                                .get("userId") + "');");
                        sellTemp.add(sellQueue);

                    } else if (buyOrderNum.longValue() == sellOrderNum.longValue()) {
                        dealNum = buyOrderNum;
                        if (dealNum.longValue() == 0) {
                            System.out.println("-----");
                        }
                        log.info("，本次成交量：" + dealNum + "，成交价：" + dealPrice);
                        //计算买单成交均价
                        buyTotalDealNum = BigDecimalUtil.getInstance()
                                .add(buyLastDealNum.toString(), dealNum.toString());

                        buyTotalDealPrice = BigDecimalUtil.getInstance()
                                .add(BigDecimalUtil.getInstance()
                                        .divide(dealNum.multiply(dealPrice), new BigDecimal("100"),
                                                2), BigDecimalUtil.getInstance()
                                        .divide(buyLastDealNum.multiply(buyLastDealPrice),
                                                new BigDecimal("100"), 2), 2);
                        buyFee = BigDecimalUtil.getInstance()
                                .multiply(buyTotalDealPrice, buyFeeRate, 2);
                        BigDecimal buyTotalAmount = BigDecimalUtil.getInstance()
                                .add(buyFee, buyTotalDealPrice, 2);//总金额（含手续费）
                        BigDecimal buyDealAvgPrice = BigDecimalUtil.getInstance()
                                .divide(buyTotalDealPrice, buyTotalDealNum, 2);
                        //计算卖单成交均价
                        sellTotalDealNum = BigDecimalUtil.getInstance()
                                .add(sellLastDealNum, dealNum, 0);

                        sellTotalDealPrice = BigDecimalUtil.getInstance()
                                .add(BigDecimalUtil.getInstance()
                                        .divide(dealNum.multiply(dealPrice), new BigDecimal("100"),
                                                2), BigDecimalUtil.getInstance()
                                        .divide(sellLastDealNum.multiply(sellLastDealPrice),
                                                new BigDecimal("100"), 2), 2);
                        sellFee = BigDecimalUtil.getInstance()
                                .multiply(sellTotalDealPrice, sellFeeRate, 2);
                        BigDecimal sellTotalAmount = BigDecimalUtil.getInstance()
                                .add(sellFee, sellTotalDealPrice, 2);//总金额（含手续费）
                        BigDecimal sellDealAvgPrice = BigDecimalUtil.getInstance()
                                .divide(sellTotalDealPrice, sellTotalDealNum, 2);

                        //卖单成交标记更新-全部成交：update trs_order set is_deal='T',deal_num=order_num ,deal_price = '"+dealPrice+"' where order_id = orderId;
                        //买单成交标记更新-部分成交：update trs_order set is_deal='T',deal_num=order_num ,deal_price = '"+dealPrice+"' where order_id = orderId;
                        execSql.append(
                                "update trs_order set is_deal='T',deal_num=order_num ,deal_price = '");
                        execSql.append(
                                sellDealAvgPrice + "',modify_time='" + now + "' where order_id = '"
                                        + sellObjMap.get("orderId") + "';");
                        execSql.append(
                                "update trs_order set is_deal='T',deal_num=order_num ,deal_price = '");
                        execSql.append(
                                buyDealAvgPrice + "',modify_time='" + now + "' where order_id = '"
                                        + buyObjMap.get("orderId") + "';");
                        buyObjMap.put("deal_num", buyTotalDealNum);
                        buyObjMap.put("deal_price",
                                buyDealAvgPrice.multiply(new BigDecimal("100")).longValue());
                        buyObjMap.put("is_deal", "T");//全部成交标记
                        //已成交的委托挂单插入到order_done表中。当前为买单

                        execSql.append(
                                "insert into trs_order_done (info_id,create_time,deal_date,deal_fee,deal_num,deal_price,deal_time,del_status,order_flag,order_id,order_no,pro_id,pro_name,pro_no,total_money,user_cname,user_ename,user_id)");
                        execSql.append("values('" + Validator.generate() + "','" + now + "','"
                                + DateUtils.Now.fmt_yyyyMMdd() + "','" + buyFee + "','"
                                + buyTotalDealNum + "','" + buyDealAvgPrice + "','" + now
                                + "','F','buy','" + buyObjMap.get("orderId") + "','" + buyObjMap
                                .get("orderNo") + "','" + proId + "','" + proName + "','" + proNo
                                + "','" + buyTotalAmount + "','" + buyObjMap.get("userCname")
                                + "','" + buyObjMap.get("userEname") + "','" + buyObjMap
                                .get("userId") + "');");
                        buyTemp.add(buyQueue);
                        //更新买方持仓：如果之前没有，则插入新的数据，如果之前已经存在仓位，则更新这条数据。
                        //联合主键：proId+userId
                        execSql.append("merge into trs_goods goods using (select '" + proId
                                + "' as pro_id,'");
                        execSql.append(buyUserId + "' as user_id from dual) m ");
                        execSql.append(
                                "on (goods.pro_id=m.pro_id and goods.user_id=m.user_id) when matched then  ");
                        if ("oracle".equalsIgnoreCase(dataType)) {
                            execSql.append(
                                    "update set goods.total_num=to_number(goods.total_num)+to_number('");
                            execSql.append(dealNum
                                    + "'), goods.forzen_num=to_number(goods.forzen_num)+to_number('");
                            execSql.append(dealNum + "'),goods.modify_time='" + now
                                    + "',goods.buy_price=round(to_number(goods.buy_price)+to_number('"
                                    + buyTotalAmount + "'),2) ");
                            execSql.append(
                                    ",goods.cost_price=round((to_number(goods.buy_price)+to_number('"
                                            + buyTotalAmount
                                            + "'))/(to_number(goods.total_num)+to_number('"
                                            + dealNum + "')),2) ");
                        } else {
                            execSql.append(
                                    "update set goods.total_num=cast(goods.total_num as unsigned int)+cast(");
                            execSql.append(dealNum
                                    + " as unsigned int), goods.forzen_num=cast(goods.forzen_num as unsigned int)+cast(");
                            execSql.append(dealNum + " as unsigned int),goods.modify_time='" + now
                                    + "',goods.buy_price=round(cast(goods.buy_price as unsigned DECIMAL)+cast("
                                    + buyTotalAmount + " as unsigned DECIMAL),2) ");
                            execSql.append(
                                    ",goods.cost_price=round((cast(goods.buy_price as unsigned DECIMAL)+cast("
                                            + buyTotalAmount
                                            + " as unsigned DECIMAL))/(cast(goods.total_num as unsigned int)+cast("
                                            + dealNum + " as unsigned int)),2) ");
                        }
                        execSql.append(
                                "when not matched then  insert (goods.goods_id,goods.user_id,goods.pro_id,pro_no,pro_name,total_num,forzen_num,create_time,del_status,user_ename,user_cname,use_num,buy_price,cost_price) ");
                        execSql.append(
                                "values ('" + Validator.generate() + "','" + buyUserId + "','"
                                        + proId + "','");
                        execSql.append(
                                proNo + "','" + proName + "','" + dealNum + "','" + dealNum + "','"
                                        + now + "','F','" + String
                                        .valueOf(buyObjMap.get("userEname")) + "','" + String
                                        .valueOf(buyObjMap.get("userCname")) + "','0','"
                                        + buyTotalAmount + "','" + BigDecimalUtil.getInstance()
                                        .divide(buyTotalAmount.toString(),
                                                buyTotalDealNum.toString(), 2) + "');");
                        sellObjMap.put("deal_num", sellTotalDealNum);
                        sellObjMap.put("deal_price", BigDecimalUtil.getInstance()
                                .multiply(sellDealAvgPrice.toString(), "100"));
                        sellObjMap.put("is_deal", "T");//全部成交标记
                        //更新卖方持仓
                        if ("oracle".equalsIgnoreCase(dataType)) {
                            execSql.append(
                                    "update trs_goods goods set goods.total_num=to_number(goods.total_num)-to_number('");
                            execSql.append(dealNum
                                    + "'),goods.forzen_num=to_number(goods.forzen_num)-to_number('");
                            execSql.append(dealNum + "'),goods.modify_time='" + now
                                    + "',goods.buy_price=round(to_number(goods.buy_price)-to_number('"
                                    + sellTotalDealPrice + "')+to_number('" + sellFee
                                    + "'),2),goods.cost_price=round((to_number(goods.buy_price)-to_number('"
                                    + sellTotalDealPrice + "')+to_number('" + sellFee
                                    + "'))/(to_number(goods.total_num)-to_number('" + dealNum
                                    + "')),2) where goods.pro_id='" + proId
                                    + "' and goods.user_id='");
                        } else {
                            execSql.append(
                                    "update trs_goods goods set goods.total_num=cast(goods.total_num as unsigned int)-cast(");
                            execSql.append(dealNum
                                    + " as unsigned int),goods.forzen_num=cast(goods.forzen_num as unsigned int)-cast(");
                            execSql.append(dealNum + " as unsigned int),goods.modify_time='" + now
                                    + "',goods.buy_price=round(cast(goods.buy_price as unsigned DECIMAL)-cast("
                                    + sellTotalDealPrice + " as unsigned DECIMAL)+cast(" + sellFee
                                    + " as unsigned DECIMAL),2),goods.cost_price=round((cast(goods.buy_price as unsigned DECIMAL)-cast("
                                    + sellTotalDealPrice + " as unsigned DECIMAL)+cast(" + sellFee
                                    + " as unsigned DECIMAL))/(cast(goods.total_num as unsigned int)-cast("
                                    + dealNum + " as unsigned int)),2) where goods.pro_id='" + proId
                                    + "' and goods.user_id='");
                        }
                        execSql.append(sellUserId + "';");
                        //插入到trp_deal表
                        execSql.append(
                                insertDeal(proId, String.valueOf(dealPrice), buyObjMap, sellObjMap,
                                        proName, String.valueOf(dealNum)));
                        //已成交的委托挂单插入到order_done表中。当前为卖单

                        execSql.append(
                                "insert into trs_order_done (info_id,create_time,deal_date,deal_fee,deal_num,deal_price,deal_time,del_status,order_flag,order_id,order_no,pro_id,pro_name,pro_no,total_money,user_cname,user_ename,user_id)");
                        execSql.append("values('" + Validator.generate() + "','" + now + "','"
                                + DateUtils.Now.fmt_yyyyMMdd() + "','" + sellFee + "','"
                                + sellTotalDealNum + "','" + sellDealAvgPrice + "','" + now
                                + "','F','sell','" + sellObjMap.get("orderId") + "','" + sellObjMap
                                .get("orderNo") + "','" + proId + "','" + proName + "','" + proNo
                                + "','" + sellTotalAmount + "','" + sellObjMap.get("userCname")
                                + "','" + sellObjMap.get("userEname") + "','" + sellObjMap
                                .get("userId") + "');");
                        sellTemp.add(sellQueue);
                        if (j < (buyList.size() - 1)) {
                            sellIndex = j + 1;
                        }
                        sellObjMap.put("is_state", "F");

                        break;
                    } else {
                        //买单剩余未成交数量<卖单剩余未成交数量，则认为买单全部成交，卖单部分成交。成交数量以小者（买单）为准
                        dealNum = buyOrderNum;
                        if (dealNum.longValue() == 0) {
                            System.out.println("-----");
                        }
                        log.info("，本次成交量：" + dealNum + "，成交价：" + dealPrice);
                        //计算买单成交均价
                        buyTotalDealNum = BigDecimalUtil.getInstance()
                                .add(buyLastDealNum.toString(), dealNum.toString());
                        buyTotalDealPrice = BigDecimalUtil.getInstance()
                                .add(BigDecimalUtil.getInstance()
                                                .divide(dealNum.multiply(dealPrice), beiBig, 2),
                                        BigDecimalUtil.getInstance()
                                                .divide(buyLastDealNum.multiply(buyLastDealPrice),
                                                        beiBig, 2), 2);
                        buyFee = BigDecimalUtil.getInstance()
                                .multiply(buyTotalDealPrice, buyFeeRate, 2);
                        BigDecimal buyTotalAmount = BigDecimalUtil.getInstance()
                                .add(buyFee.toString(), buyTotalDealPrice.toString());//总金额（含手续费）
                        BigDecimal buyDealAvgPrice = BigDecimalUtil.getInstance()
                                .divide(buyTotalDealPrice, buyTotalDealNum, 2);
                        //计算卖单成交均价
                        sellTotalDealNum = BigDecimalUtil.getInstance()
                                .add(sellLastDealNum.toString(), dealNum.toString());
                        sellTotalDealPrice = BigDecimalUtil.getInstance()
                                .add(BigDecimalUtil.getInstance()
                                                .divide(dealNum.multiply(dealPrice), beiBig, 2),
                                        BigDecimalUtil.getInstance()
                                                .divide(sellLastDealNum.multiply(sellLastDealPrice),
                                                        beiBig, 2), 2);
                        sellFee = BigDecimalUtil.getInstance()
                                .multiply(sellTotalDealPrice, sellFeeRate, 2);
                        BigDecimal sellTotalAmount = BigDecimalUtil.getInstance()
                                .add(sellFee.toString(), sellTotalDealPrice.toString());//总金额（含手续费）
                        BigDecimal sellDealAvgPrice = BigDecimalUtil.getInstance()
                                .divide(sellTotalDealPrice, sellTotalDealNum, 2);
                        //买单成交标记更新-全部成交：update trs_order set is_deal='T',deal_num=order_num ,deal_price = '"+dealPrice+"' where order_id = orderId;
                        //卖单成交标记更新-部分成交：update trs_order set is_deal='T0',deal_num='"+dealNum+"' ,deal_price = '"+dealPrice+"' where order_id = orderId;
                        execSql.append(
                                "update trs_order set is_deal='T',deal_num=order_num ,deal_price = '");
                        execSql.append(
                                buyDealAvgPrice + "',modify_time='" + now + "' where order_id = '"
                                        + buyObjMap.get("orderId") + "';");
                        execSql.append(
                                "update trs_order set is_deal='T0',deal_num='" + sellTotalDealNum);
                        execSql.append(
                                "' ,deal_price = '" + sellDealAvgPrice + "',modify_time='" + now
                                        + "' where order_id ='" + sellObjMap.get("orderId") + "';");
                        buyObjMap.put("deal_num", buyTotalDealNum);
                        buyObjMap.put("deal_price", BigDecimalUtil.getInstance()
                                .multiply(buyDealAvgPrice.toString(), "100"));
                        buyObjMap.put("is_deal", "T");//全部成交标记
                        //已成交的委托挂单插入到order_done表中。当前为买单

                        execSql.append(
                                "insert into trs_order_done (info_id,create_time,deal_date,deal_fee,deal_num,deal_price,deal_time,del_status,order_flag,order_id,order_no,pro_id,pro_name,pro_no,total_money,user_cname,user_ename,user_id)");
                        execSql.append("values('" + Validator.generate() + "','" + now + "','"
                                + DateUtils.Now.fmt_yyyyMMdd() + "','" + buyFee + "','"
                                + buyTotalDealNum + "','" + buyDealAvgPrice + "','" + now
                                + "','F','buy','" + buyObjMap.get("orderId") + "','" + buyObjMap
                                .get("orderNo") + "','" + proId + "','" + proName + "','" + proNo
                                + "','" + buyTotalAmount + "','" + buyObjMap.get("userCname")
                                + "','" + buyObjMap.get("userEname") + "','" + buyObjMap
                                .get("userId") + "');");

                        buyTemp.add(buyQueue);
                        //更新买方持仓：如果之前没有，则插入新的数据，如果之前已经存在仓位，则更新这条数据。
                        //联合主键：proId+userId
                        execSql.append("merge into trs_goods goods using (select '" + proId
                                + "' as pro_id,'");
                        execSql.append(buyUserId + "' as user_id from dual) m ");
                        execSql.append(
                                "on (goods.pro_id=m.pro_id and goods.user_id=m.user_id) when matched then  ");
                        if ("oracle".equalsIgnoreCase(dataType)) {
                            execSql.append(
                                    "update set goods.total_num=to_number(goods.total_num)+to_number('");
                            execSql.append(dealNum
                                    + "'), goods.forzen_num=to_number(goods.forzen_num)+to_number('");
                            execSql.append(dealNum + "'),goods.modify_time='" + now
                                    + "',goods.buy_price=round(to_number(goods.buy_price)+to_number('"
                                    + buyTotalAmount + "'),2) ");
                            execSql.append(
                                    ",goods.cost_price=round((to_number(goods.buy_price)+to_number('"
                                            + buyTotalAmount
                                            + "'))/(to_number(goods.total_num)+to_number('"
                                            + dealNum + "')),2) ");
                        } else {
                            execSql.append(
                                    "update set goods.total_num=cast(goods.total_num as unsigned int)+cast(");
                            execSql.append(dealNum
                                    + " as unsigned int), goods.forzen_num=cast(goods.forzen_num as unsigned int)+cast(");
                            execSql.append(dealNum + " as unsigned int),goods.modify_time='" + now
                                    + "',goods.buy_price=round(cast(goods.buy_price as unsigned DECIMAL)+cast("
                                    + buyTotalAmount + " as unsigned DECIMAL),2) ");
                            execSql.append(
                                    ",goods.cost_price=round((cast(goods.buy_price as unsigned DECIMAL)+cast("
                                            + buyTotalAmount
                                            + " as unsigned DECIMAL))/(cast(goods.total_num as unsigned int)+cast("
                                            + dealNum + " as unsigned int)),2) ");
                        }
                        execSql.append(
                                "when not matched then  insert (goods.goods_id,goods.user_id,goods.pro_id,pro_no,pro_name,total_num,forzen_num,create_time,del_status,user_ename,user_cname,use_num,buy_price,cost_price) ");
                        execSql.append(
                                "values ('" + Validator.generate() + "','" + buyUserId + "','"
                                        + proId + "','");
                        execSql.append(
                                proNo + "','" + proName + "','" + dealNum + "','" + dealNum + "','"
                                        + now + "','F','" + String
                                        .valueOf(buyObjMap.get("userEname")) + "','" + String
                                        .valueOf(buyObjMap.get("userCname")) + "','0','"
                                        + buyTotalAmount + "','" + BigDecimalUtil.getInstance()
                                        .divide(buyTotalAmount.toString(),
                                                buyTotalDealNum.toString(), 2) + "');");
                        sellObjMap.put("deal_num", sellTotalDealNum);
                        sellObjMap.put("deal_price", sellDealAvgPrice.multiply(beiBig).longValue());
                        sellObjMap.put("is_deal", "T0");//部分成交标记
                        //更新卖方持仓
                        if ("oracle".equalsIgnoreCase(dataType)) {
                            execSql.append(
                                    "update trs_goods goods set goods.total_num=to_number(goods.total_num)-to_number('");
                            execSql.append(dealNum
                                    + "'),goods.forzen_num=to_number(goods.forzen_num)-to_number('");
                            execSql.append(dealNum + "'),goods.modify_time='" + now
                                    + "',goods.buy_price=round(to_number(goods.buy_price)-to_number('"
                                    + sellTotalDealPrice + "')+to_number('" + sellFee
                                    + "'),2),goods.cost_price=round((to_number(goods.buy_price)-to_number('"
                                    + sellTotalDealPrice + "')+to_number('" + sellFee
                                    + "'))/(to_number(goods.total_num)-to_number('" + dealNum
                                    + "')),2) where goods.pro_id='" + proId
                                    + "' and goods.user_id='");
                        } else {
                            execSql.append(
                                    "update trs_goods goods set goods.total_num=cast(goods.total_num as unsigned int)-cast(");
                            execSql.append(dealNum
                                    + " as unsigned int),goods.forzen_num=cast(goods.forzen_num as unsigned int)-cast(");
                            execSql.append(dealNum + " as unsigned int),goods.modify_time='" + now
                                    + "',goods.buy_price=round(cast(goods.buy_price as unsigned DECIMAL)-cast("
                                    + sellTotalDealPrice + " as unsigned DECIMAL)+cast(" + sellFee
                                    + " as unsigned DECIMAL),2),goods.cost_price=round((cast(goods.buy_price as unsigned DECIMAL)-cast("
                                    + sellTotalDealPrice + " as unsigned DECIMAL)+cast(" + sellFee
                                    + " as unsigned DECIMAL))/(cast(goods.total_num as unsigned int)-cast("
                                    + dealNum + " as unsigned int)),2) where goods.pro_id='" + proId
                                    + "' and goods.user_id='");
                        }
                        execSql.append(sellUserId + "';");
                        execSql.append(
                                insertDeal(proId, String.valueOf(dealPrice), buyObjMap, sellObjMap,
                                        proName, String.valueOf(dealNum)));
                        if (i < (sellList.size() - 1)) {
                            buyIndex = i + 1;
                        }
                        sellObjMap.put("is_state", "F");
                        break;
                    }
                } else {
                    log.info("buy" + i + "买价 < sell" + j + "卖价，则匹配失败！无法成交！");
                    isRun = false;
                    break;
                }
                sellObjMap.put("is_state", "F");
            }
            buyObjMap.put("is_state", "F");
        }
        buyList.removeAll(buyTemp);
        sellList.removeAll(sellTemp);
        System.out.println("本次撮合将会执行SQL》》》》");
        if (execSql.toString().length() > 0) {
            String sql[] = execSql.toString().split(";");
            for (String str : sql) {
                System.out.println(str);
            }
        }
        return execSql.toString();
    }

    private String insertDeal(String proId, String dealPrice, DataMap buyObjMap, DataMap sellObjMap,
            String proName, String dealNum) {
        StringBuffer sb = new StringBuffer("");

        if (NumberUtils.getDouble(dealPrice, 0, true) > 0
                && NumberUtils.getDouble(dealNum, 0, true) > 0) {
            String buyEname = String.valueOf(buyObjMap.get("userEname"));
            String buyCname = String.valueOf(buyObjMap.get("userCname"));
            String buyUserId = String.valueOf(buyObjMap.get("userId"));
            String buyFeeRatio = String.valueOf(buyObjMap.get("feeRatio"));
            String buyOrderNo = String.valueOf(buyObjMap.get("orderNo"));
            String buyOrderPrice = String.valueOf(buyObjMap.get("orderPrice"));

            String sellEname = String.valueOf(sellObjMap.get("userEname"));
            String sellCname = String.valueOf(sellObjMap.get("userCname"));
            String sellUserId = String.valueOf(sellObjMap.get("userId"));
            String sellFeeRatio = String.valueOf(sellObjMap.get("feeRatio"));
            String sellOrderNo = String.valueOf(sellObjMap.get("orderNo"));

            //成交均价
            double avDealPrice = NumberUtils.divide(Double.valueOf(dealPrice), 100, 2);
            //实际成交额
            double totalMoney = NumberUtils.multiply(avDealPrice, Double.valueOf(dealNum), 2);
            //卖方手续费
            double sellFeeRate = NumberUtils
                    .divide(Double.valueOf(sellFeeRatio), 100);//除以100，因为页面设置的单位是%
            double sellFee = NumberUtils.multiply(sellFeeRate, totalMoney, 2);
            //买方手续费
            double buyFeeRate = NumberUtils
                    .divide(Double.valueOf(buyFeeRatio), 100);//除以100，因为页面设置的单位是%
            double buyFee = NumberUtils.multiply(buyFeeRate, totalMoney, 2);

            String contractNo = "D" + new Date().getTime();
            sb.append("insert into trp_deal (");
            sb.append(
                    "buy_user_ename,buy_user_cname,buyer_id,seller_id,sell_user_ename,sell_user_cname,");
            sb.append(
                    "pro_id,pro_name,deal_price,deal_num,deal_money,deal_time,create_time,deal_status,deal_id,buy_fee,sell_fee,contract_no,buy_order_id,sell_order_id,buy_order_no,sell_order_no");//,contract_no");
            sb.append(") values(");
            sb.append("'" + buyEname + "',");
            sb.append("'" + buyCname + "',");
            sb.append("'" + buyUserId + "',");
            sb.append("'" + sellUserId + "',");
            sb.append("'" + sellEname + "',");
            sb.append("'" + sellCname + "',");
            sb.append("'" + proId + "',");
            sb.append("'" + proName + "',");
            sb.append("'" + avDealPrice + "','" + dealNum + "',");
            sb.append("'" + totalMoney + "',");
            sb.append("'" + DateUtils.Now.fmt_yyyyMMdd_HHmmss() + "',");
            sb.append("'" + DateUtils.Now.fmt_yyyyMMdd_HHmmss() + "',");
            sb.append("'1','" + Validator.generate() + "',");//成交状态
            sb.append("'" + buyFee + "',");
            sb.append("'" + sellFee + "',");
            sb.append("'" + contractNo + "',");//成交合同编号
            sb.append("'" + String.valueOf(buyObjMap.get("orderId")) + "',");
            sb.append("'" + String.valueOf(sellObjMap.get("orderId")) + "',");
            sb.append("'" + buyOrderNo + "',");
            sb.append("'" + sellOrderNo + "'");
            sb.append(");");

            String outUserSettleNo = getUserSettleNo(buyEname);
            String inUserSettleNo = getUserSettleNo(sellEname);
            String jysFundsId = Constant.getJysFundsId();

            //1.买卖双方资金划转
            if (totalMoney > 0) {
                toFundsMove(contractNo, outUserSettleNo, inUserSettleNo, Constant.Funds.DELV,
                        totalMoney, "委托成交");
            }
            //2.买方交纳手续费
            if (buyFee > 0) {
                toFundsMove(contractNo, outUserSettleNo, jysFundsId, Constant.Funds.FBDV, buyFee,
                        "交易手续费");
            }
            //3.卖方交纳手续费
            if (sellFee > 0) {
                toFundsMove(contractNo, inUserSettleNo, jysFundsId, Constant.Funds.FADV, sellFee,
                        "交易手续费");
            }

            //4.买方退还多冻结资金。（buy买单每成交一次并且成交价和委托价不相同时就现计算需要退的资金）。
            System.out.println("成交价==========" + dealPrice);
            if ("buy".equals(String.valueOf(buyObjMap.get("orderFlag"))) && (
                    Double.valueOf(buyOrderPrice) != Double.valueOf(dealPrice))) {
                double buyMoneyYin = NumberUtils
                        .multiply(Double.valueOf(dealNum), Double.valueOf(buyOrderPrice), 2);
                double buyFeeYin = NumberUtils.multiply(buyMoneyYin, buyFeeRate, 2);
                double buyTotalMoneyYin = NumberUtils.add(buyMoneyYin, buyFeeYin);
                double nowTotalMoney = NumberUtils.add(totalMoney, buyFee);
                double nowUnforzenMoney = NumberUtils.subtract(buyTotalMoneyYin, nowTotalMoney);
                log.info("buy[" + buyOrderNo + "]买单委托成交[" + dealNum + "]量，委托时按[" + buyOrderPrice
                        + "]元冻结计划支出[" + buyTotalMoneyYin + "]，而实际以[" + dealPrice + "]成交故只是支出["
                        + nowTotalMoney + "]");
                log.info("buy[" + buyOrderNo + "]买单本次应该退回多冻结金额：" + nowUnforzenMoney);
                if (nowUnforzenMoney > 0) {
                    //保证冻结资金>=退还资金，如果小于退还资金，则清空冻结资金。
                    toFundsForzenOrUn(outUserSettleNo, Constant.Funds.CBOD, nowUnforzenMoney,
                            buyOrderNo, "冻结资金退还");
                }
            }

        } else {
            log.info("成交价[" + dealPrice + "],成交量[" + dealNum + "]有问题，不添加deal，不交割处理资金！");
        }
        return sb.toString();
    }

    /**
     * 计算订单成交均价
     * description:
     *
     * @return 总体成交均价
     */
    private double countDealAvgPrice(long totalMoney, long totaleDealNum) {
        double dealAvgPrice = NumberUtil.div(totalMoney, totaleDealNum, 2);
        return dealAvgPrice;
    }

    /**
     * 清空队列数据
     */
    @SuppressWarnings("rawtypes")
    public boolean clearData(ParamsVo vo) {
        boolean flag = false;
        //清理中服务
        String initFlag = String.valueOf(
                SystemTools.getInstance().getCache("").getCacheObjectByKey("InitDealMatching"));
        if ("T".equals(initFlag)) {
            //清理 todo
            StringBuffer sb = new StringBuffer();
            String nowDate = DateUtils.Now.fmt_yyyyMMdd();
            sb.append("update trs_order set is_kill='T' where is_deal='F' and create_time like '"
                    + nowDate + "%';");
            vo.setParams("sqlStr", sb.toString());
            vo.setParams("ifUpdate", "dddd");//将今天所有未成交的订单改为取消
            saveInvoke(vo);
            //清理缓存队列
            SystemTools.getInstance().getCache("").removeCacheObject("MATCH_PRODUCT_FLAG");
            SystemTools.getInstance().getCache("").removeCacheObject("MATCH_INDEX");
            //清理正常完成后，自动转为暂停服务状态
            SystemTools.getInstance().getCache("").createCacheObject("InitDealMatching", "F");
        }
        return flag;
    }

    /**
     * description:  计算成交价格
     * 撮合成交的前提是：买入价（A）必须大于或等于卖出价（B），即A>=B。
     * 计算依据：计算机在撮合时实际上是依据前一笔成交价而定出最新成交价的。
     * 假设：前一笔的成交价格为C，最新成交价为D；
     * 则，当
     * A<=C时，D=A；（如果前一笔成交价高于 或等于买入价，则最新成交价就是买入价）
     * B>=C时，D=B；（如果前一笔成交价低于或等于卖出价，则最新成交价就是卖出价）
     * B<C<A时，D=C；（如果前一笔成交价在卖出价与买入价 之间，则最新成交价就是前一笔的成交价）
     */
    @SuppressWarnings("rawtypes")
    private String getDealPrice(String proId, String buyPrice, String sellPrice) {
        String price = String.valueOf(
                SystemTools.getInstance().getCache("").getCacheObjectByKey("price_" + proId));
        String resultPrice = "";
        if (Validator.isNull(price)) {
            MethodParam param = new MethodParam("ByObjInfo", "", "", entityName);
            param.setParams("dyncSql",
                    "select open_price from t_quotation where pro_id='" + proId + "'");
            Map obj = (Map) trpCateDao.selectSingle(param);
            price = String.valueOf(obj.get("openPrice"));
        }
        double dprice = Double.valueOf(price);
        double bprice = Double.valueOf(buyPrice);
        double sprice = Double.valueOf(sellPrice);
        if (bprice == sprice) {
            resultPrice = buyPrice;
        } else {
            if (bprice <= dprice) {
                resultPrice = buyPrice;
            } else if (sprice >= dprice) {
                resultPrice = sellPrice;
            } else if (sprice < dprice && dprice < bprice) {
                resultPrice = price;
            }
        }
        if (Validator.isNull(resultPrice))
            resultPrice = "0";
        SystemTools.getInstance().getCache("").createCacheObject("price_" + proId, resultPrice);
        return resultPrice;
    }

    private long getDealPriceNew(String proId, long buyPrice, long sellPrice) {
        String price = String.valueOf(
                SystemTools.getInstance().getCache("").getCacheObjectByKey("price_" + proId));
        long resultPrice = buyPrice;
        if (Validator.isNull(price)) {
            MethodParam param = new MethodParam("ByObjInfo", "", "", entityName);
            param.setParams("dyncSql",
                    "select open_price from t_quotation where pro_id='" + proId + "'");
            Map obj = (Map) trpCateDao.selectSingle(param);
            price = String.valueOf(obj.get("openPrice"));
            price = String.valueOf(Math.round((Double.valueOf(price) * 100)));
        }
        long dprice = Long.valueOf(price);
        resultPrice = Constant.getABCD(buyPrice, sellPrice, dprice);
        SystemTools.getInstance().getCache("")
                .createCacheObject("price_" + proId, String.valueOf(resultPrice));
        return resultPrice;
    }

    // 处理剩余的申报数据
    private void handleRestOrder(Map<String, Object> order, IndexList il, Keyword aKeyword) {
        int orderNum = Integer.valueOf(String.valueOf(order.get("orderNum"))).intValue();
        if (orderNum > 0) {
            il.insertOrUpdate(aKeyword, order);
        }
    }

    /**
     * description:  拼装获取order信息的sql
     */
    private String getOrderSql(String orderBy, String type, String sysName) {
        String key = "order_tableAttr";
        String content = String
                .valueOf(SystemTools.getInstance().getCache("").getCacheObjectByKey(key));
        String cloums = "";
        if (Validator.isNull(content)) {
            List<PubMetadata> list = InfoReleaseCoreCleint.getInstance()
                    .getMetadatas("order", sysName);
            StringBuffer sb = new StringBuffer("");
            for (PubMetadata pm : list) {
                sb.append("," + pm.getDataAttr());
            }
            sb.deleteCharAt(0);
            cloums = sb.toString();
        } else {
            String attrStr[] = content.split(";");
            cloums = attrStr[1];
        }
        //cloums += " from trs_order s where s.is_kill='F' and s.is_deal='F' and s.del_status='F' order by order_time asc";
        //order_flag=buy/sell
        //return "select " + cloums;
        String nowDate = DateUtils.Now.fmt_yyyyMMdd();
        return "select * from trs_order s where s.create_time like '" + nowDate
                + "%' and s.is_kill='F' and (s.is_deal='F' or s.is_deal='T0') and s.del_status='F' and order_flag='"
                + type + "' order by " + orderBy;
    }

    public void setTrpCateDao(IDao trpCateDao) {
        this.trpCateDao = trpCateDao;
    }

    /**
     * 资金冻结或者解冻
     *
     * @param userSettleNo 资金账号
     * @param tradeType 冻结=Constant.Funds.PBOD，解冻=Constant.Funds.CBOD
     * @param money 操作金额
     * @param orderNo 操作流水号
     * @param remark 备注描述
     */
    private boolean toFundsForzenOrUn(String userSettleNo, String tradeType, double money,
            String orderNo, String remark) {
        double amount = NumberUtils.multiply(money, 100, 2);//扩大100倍
        Map<String, String> prarmMap1 = new HashMap<String, String>();
        prarmMap1.put("tradeType", tradeType);//定值
        prarmMap1.put("userId", userSettleNo);//账户
        prarmMap1.put("amt", Long.toString(Math.round(amount)));//操作金额
        //添加参数组
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        list.add(prarmMap1);
        //补充参数
        Map<String, Object> fundsMap = new HashMap<String, Object>();
        fundsMap.put("funds", list);
        fundsMap.put("actionId", orderNo);//业务流水号
        fundsMap.put("remark", remark);//业务描述
        ResultEntity entityFunds = FundsUtil.doFunds(fundsMap.get("remark").toString(), fundsMap);
        if ("false".equals(entityFunds.getResult())) {
            log.error("资金处理通信失败！" + remark);
            return false;
        }
        if (!"true".equals(entityFunds.getEntity().toString())) {
            log.error("资金处理失败！" + entityFunds.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 资金划转接口
     *
     * @param tradeNo 操作流水号
     * @param outUserSettleNo 付款方资金账号
     * @param inUserSettleNo 收款方资金账号
     * @param tradeType 转移类型，参照常量Constant.Funds.
     * @param money 操作金额
     * @param remark
     * @return
     */
    private boolean toFundsMove(String tradeNo, String outUserSettleNo, String inUserSettleNo,
            String tradeType, double money, String remark) {
        if (StrUtil.isNull(outUserSettleNo)) {
            log.error(tradeNo + "-" + tradeType + "，付款方资金账号为空！导致资金划转失败。");
            return false;
        }
        if (StrUtil.isNull(inUserSettleNo)) {
            log.error(tradeNo + "-" + tradeType + "，收款方资金账号为空！导致资金划转失败。");
            return false;
        }

        //公用参数定义
        Map<String, String> prarmMap1 = new HashMap<String, String>();

        double amount = NumberUtils.multiply(money, 100, 2);

        prarmMap1.put("tradeType", tradeType);//定值
        prarmMap1.put("fromUserId", outUserSettleNo);//付款方账户
        prarmMap1.put("toUserId", inUserSettleNo);//收款方账户
        prarmMap1.put("amt", Long.toString(Math.round(amount)));//操作金额

        //添加参数组
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        list.add(prarmMap1);
        //补充参数
        Map<String, Object> fundsMap = new HashMap<String, Object>();
        fundsMap.put("funds", list);
        fundsMap.put("actionId", tradeNo);//业务流水号
        fundsMap.put("remark", remark);//业务描述
        ResultEntity entityFunds = FundsUtil.doFunds(fundsMap.get("remark").toString(), fundsMap);
        if ("false".equals(entityFunds.getResult())) {
            log.error("资金处理通信失败！" + remark);
            return false;
        }
        if (!"true".equals(entityFunds.getEntity().toString())) {
            log.error("资金处理失败！" + entityFunds.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 根据登录账号获取资金账号
     *
     * @param createUserEname
     * @return
     */
    private String getUserSettleNo(String createUserEname) {
        ResultEntity ret = FundsUtil.selectFundsMyAccountByCreateUserEname(createUserEname);
        if ("true".equals(ret.getResult()) && ret.getEntity() != null) {
            JSONObject svmUser = (JSONObject) ret.getEntity();
            if (svmUser != null) {
                return String.valueOf(svmUser.get("userName"));
            }
        }
        return null;
    }

}
